#include <QtGui>
#include <QDir>
#include "FtpUpdate.h"
#include "ftpprogressbar.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
	myCom(NULL),
	openFindDialogAction(NULL),
	findNextAction(NULL)
{
    ui->setupUi(this);
	connect(ui->infoLabel, SIGNAL(linkActivated(const QString&)), this, SLOT(mailTo(const QString&)));
	float currentVersion = QApplication::applicationVersion().toFloat();
	QString infoStr = ui->infoLabel->text();
	QString tmp = QString::number(currentVersion,'f');

	int len = 0;
	for (len = tmp.length() - 1; len > 0; len--)
	{
		if (QChar('0') != tmp[len])
		{
			len++;
			break;
		}
	}

	infoStr.append(QString("Ver. %1").arg(tmp.left(len)));
	ui->infoLabel->setText(infoStr);
    ui->closeMyComBtn->setEnabled(false);
    ui->sendMsgBtn->setEnabled(false);
    ui->sendMsgBtn->setMaximumWidth(ui->sendMsgBtn->sizeHint().width()/2);
	ui->textRadioButton->setChecked(true);

    ui->cleanMsgList->setMaximumWidth(ui->sendMsgBtn->sizeHint().width()/3);
    connect(ui->cleanMsgList, SIGNAL(clicked()), ui->sendMsgLineEditComboBox, SLOT(clear()));

    ui->sendMsgLineEditComboBox->setEditable(true);
    ui->sendMsgLineEditComboBox->setMaxCount(30);
    ui->sendMsgLineEditComboBox->setMaxVisibleItems(15);
    ui->sendMsgLineEditComboBox->setInsertPolicy(QComboBox::InsertAtTop);
    connect(ui->sendMsgLineEditComboBox->lineEdit(),SIGNAL(returnPressed()), this, SLOT(on_sendMsgLineEditComboBox_returnPressed()));
	
	openFindDialogAction = new QShortcut(QKeySequence::Find, this);
	connect(openFindDialogAction,SIGNAL(activated()), this, SLOT(openFindDialog()));

	findNextAction = new QShortcut(tr("F3"), this);
	connect(findNextAction,SIGNAL(activated()), this, SLOT(findText()));
	
	qDebug()<<"applicationDirPath : "<<QApplication::applicationDirPath();
	qDebug()<<"applicationFilePath : "<<QApplication::applicationFilePath();
	QString filePath = QApplication::applicationFilePath();
	int namePosition = filePath.lastIndexOf("/");
	qDebug()<<"file name position start "<<namePosition;
	qDebug()<<filePath.remove(0,++namePosition);
	
	namePosition = filePath.lastIndexOf(".");
	qDebug()<<filePath.remove(namePosition, filePath.length() - namePosition);

    setWindowTitle(filePath + QApplication::applicationVersion());
    loadCustomSetting();

	removeBakFile();
	QStringList argList = QApplication::arguments();
	if ((argList.count() == 2) && ("nc" == argList.at(1)))
	{
		this->show();
		return;
	}
	UpdateVersion();
}
void MainWindow::mailTo(const QString& address)
{
	QDesktopServices::openUrl(QUrl(address));
}

void MainWindow::removeBakFile()
{
	QDir dir(QApplication::applicationDirPath()); /*= QDir::current()*/;
	QStringList filters;
	filters<<"VantageControllerPortTest*.exe.vcptbak";
	QStringList fileListStr = dir.entryList(filters);

	QStringListIterator fileNameIterator(fileListStr);

	while (fileNameIterator.hasNext())
	{
		while(1)
		{
			if (dir.remove(fileNameIterator.next()))
			{
				break;
			}			
		}
	}
}

void MainWindow::UpdateVersion()
{
	connect(FtpUpdate::instance(),SIGNAL(requestFtpResult(int)), this, SLOT(ftpResult(int)));
	connect(FtpUpdate::instance(), SIGNAL(progressBarClosedSignal()), this, SLOT(show()));
	ftpFileNameID = FtpUpdate::instance()->requestGetFileName();	
}

float MainWindow::GetVersionFromPath(const QString& path)
{
	float vertion = 1.0;
	QRegExp rx("\\d*\\.\\d+");
	int pos = rx.indexIn(path);

	if(-1 != pos)
	{		
		QString value = rx.cap(0);
		vertion = value.toFloat();
	}

	return vertion;
}

bool MainWindow::IsNeedUpdate()
{
	bool result = false;
	float currentVersion = QApplication::applicationVersion().toFloat();
	qDebug()<<"current version is "<<currentVersion;
	
	float ftpFileVersion = GetVersionFromPath(FtpUpdate::instance()->getFileName());
	qDebug()<<"New file version is "<<ftpFileVersion;

	if (ftpFileVersion > currentVersion)
	{
		result = true;
	}

	return result;
}

void MainWindow::ftpResult(int Id)
{
	if (ftpDownloadID == Id)
	{
		qDebug()<<"New file "<<FtpUpdate::instance()->getFileName()<<"has been downloaded";

		QString localFileFullName = QApplication::applicationFilePath();
		QString localFileRename = QApplication::applicationFilePath().remove(".exe") + QApplication::applicationVersion() + ".exe.vcptbak";

		QFile file(localFileFullName);
		file.rename(localFileRename);

		QString downloadFileFullName = QApplication::applicationDirPath() + "/" + FtpUpdate::instance()->getFileName();
		QString downloadFileRename = QApplication::applicationDirPath() + "/" + QApplication::applicationName();

		file.setFileName(downloadFileFullName);
		file.rename(downloadFileRename);

		QMessageBox::information(this,tr("Update info"), tr("Update finished.\n\nPlease push Quit and restart this tool."), tr("Quit"));
		QApplication::quit();
		QProcess::startDetached(QApplication::applicationName() + " nc");		
	} 
	else if(ftpFileNameID == Id)
	{
		if (IsNeedUpdate())
		{
			QString filePath = QApplication::applicationDirPath();
			ftpDownloadID = FtpUpdate::instance()->requestDownloadFile(filePath);
		}
		else
		{
			this->show();			
		}
	}
	else if(0xffffffff == Id)
	{
		QDir dir(QApplication::applicationDirPath()); /*= QDir::current()*/;
		dir.remove(FtpUpdate::instance()->getFileName());
		
		qDebug()<<"New file "<<FtpUpdate::instance()->getFileName()<<"download has been canceled";

		QString exec = QApplication::applicationFilePath() + " nc";
		QApplication::quit();
		QProcess::startDetached(exec);		
	}
}

void MainWindow::openFindDialog()
{
	bool ok = false;
	QString temp = QInputDialog::getText(this, tr("Find Command"), tr("Command :"), QLineEdit::Normal, findString, &ok);
	if(ok)
	{
		findString = temp;
		findText();
	}
}

void MainWindow::findText()
{
	if (!ui->textBrowser->find(findString))
	{
		QTextCursor cursor(ui->textBrowser->document());
		cursor.movePosition(QTextCursor::Start);
		ui->textBrowser->setTextCursor(cursor);
		ui->textBrowser->find(findString);
	}	
}

MainWindow::~MainWindow()
{
    saveCustomSetting();    
    if(myCom && myCom->isOpen())
		myCom->close();

    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::readMyCom()
{
    QByteArray temp = myCom->readAll();
    QTextCursor cursor(ui->textBrowser->document());
    cursor.movePosition(QTextCursor::End);
    ui->textBrowser->setTextCursor(cursor);
    ui->textBrowser->setTextColor(Qt::red);
	if (DDY_TEXT == DataDisplayIndex())
	{
		ui->textBrowser->insertPlainText(EncodebyDataDisplay(temp));
	}
	else if(DDY_HEX == DataDisplayIndex())
	{
		ui->textBrowser->insertPlainText(EncodebyDataDisplay(temp) + "\n");
	}    
}

void MainWindow::on_pushButton_clicked()
{
    ui->textBrowser->clear();
}

void MainWindow::on_openMyComBtn_clicked()
{
    QString portName = ui->portNameComboBox->currentText();
    myCom = new Win_QextSerialPort(portName, QextSerialBase::EventDriven);
    if(!myCom->open(QIODevice::ReadWrite))
    {
        QMessageBox::warning(this, tr("warning"), tr("%1 has been used or not exist, please check the %1 connection then try open again").arg(portName));
        return;
    }

    QString  baudRate = ui->baudRateComboBox->currentText();
    if( baudRate == tr("110"))
        myCom->setBaudRate(BAUD110);
    else if( baudRate == tr("300"))
        myCom->setBaudRate(BAUD300);
    else if( baudRate == tr("600"))
        myCom->setBaudRate(BAUD600);
    else if( baudRate == tr("1200"))
        myCom->setBaudRate(BAUD1200);
    else if( baudRate == tr("2400"))
        myCom->setBaudRate(BAUD2400);
    else if( baudRate == tr("4800"))
        myCom->setBaudRate(BAUD4800);
    else if( baudRate == tr("9600"))
        myCom->setBaudRate(BAUD9600);
    else if( baudRate == tr("14400"))
        myCom->setBaudRate(BAUD14400);
    else if( baudRate == tr("19200"))
        myCom->setBaudRate(BAUD19200);
    else if( baudRate == tr("38400"))
        myCom->setBaudRate(BAUD38400);
    else if( baudRate == tr("56000"))
        myCom->setBaudRate(BAUD56000);
    else if( baudRate == tr("57600"))
        myCom->setBaudRate(BAUD57600);
    else if( baudRate == tr("115200"))
        myCom->setBaudRate(BAUD115200);
    else if( baudRate == tr("128000"))
        myCom->setBaudRate(BAUD128000);
    else if( baudRate == tr("256000"))
        myCom->setBaudRate(BAUD256000);

    QString dataBits = ui->dataBitsComboBox->currentText();
    if(dataBits == tr("5"))
        myCom->setDataBits(DATA_5);
    else if(dataBits == tr("6"))
        myCom->setDataBits(DATA_6);
    else if(dataBits == tr("7"))
        myCom->setDataBits(DATA_7);
    else if(dataBits == tr("8"))
        myCom->setDataBits(DATA_8);

    QString parity = ui->parityComboBox->currentText();
    if(parity == tr("None"))
        myCom->setParity(PAR_NONE);
    else if(parity == tr("Odd"))
        myCom->setParity(PAR_ODD);
    else if(parity == tr("Even"))
        myCom->setParity(PAR_EVEN);

    QString stopBits = ui->stopBitsComboBox->currentText();
    if(stopBits == tr("1"))
        myCom->setStopBits(STOP_1);
    else if(stopBits == tr("2"))
        myCom->setStopBits(STOP_2);

    myCom->setFlowControl(FLOW_OFF);
    //myCom->setTimeout(1);

    connect(myCom, SIGNAL(readyRead()), this,SLOT(readMyCom()));
    ui->openMyComBtn->setEnabled(false);
    ui->closeMyComBtn->setEnabled(true);
    ui->sendMsgBtn->setEnabled(true);
    ui->baudRateComboBox->setEnabled(false);
    ui->portNameComboBox->setEnabled(false);
    ui->dataBitsComboBox->setEnabled(false);
    ui->stopBitsComboBox->setEnabled(false);
    ui->parityComboBox->setEnabled(false);
}

void MainWindow::on_closeMyComBtn_clicked()
{
    myCom->close();
    ui->openMyComBtn->setEnabled(true);
    ui->closeMyComBtn->setEnabled(false);
    ui->sendMsgBtn->setEnabled(false);
    ui->baudRateComboBox->setEnabled(true);
    ui->portNameComboBox->setEnabled(true);
    ui->dataBitsComboBox->setEnabled(true);
    ui->stopBitsComboBox->setEnabled(true);
    ui->parityComboBox->setEnabled(true);
}

void MainWindow::writePort()
{
    QString strtext = ui->sendMsgLineEditComboBox->lineEdit()->text();
	QByteArray feedBack = DecodebyDataDisplay(strtext);
	if ((strtext.isEmpty()) || (feedBack.isEmpty()))
	{
		return;
	}	

    QString strDelimiter = ui->delimiterLineEdit->text();
    QStringList delimiterList = strDelimiter.split("~");
    QStringListIterator iterator(delimiterList);
    while(iterator.hasNext())
    {
        bool ok;
        int hex = iterator.next().toInt(&ok, 16);
        if(ok)
		{
            strtext.append(hex);
			feedBack.append(hex);
		}
    }

    myCom->write(feedBack);

    QTextCursor cursor(ui->textBrowser->document());
    cursor.movePosition(QTextCursor::End);
    ui->textBrowser->setTextCursor(cursor);
    ui->textBrowser->setTextColor(Qt::blue);
    ui->textBrowser->insertPlainText(strtext+"\n");

    QString text = ui->sendMsgLineEditComboBox->lineEdit()->text();
	int position = ui->sendMsgLineEditComboBox->findText(text);
	if(position == -1)
	{
		ui->sendMsgLineEditComboBox->insertItem(0,text);
	}
}

void MainWindow::on_sendMsgBtn_clicked()
{
    writePort();
}

void MainWindow::on_sendMsgLineEditComboBox_returnPressed()
{
    if(ui->sendMsgBtn->isEnabled())
    {
        writePort();
    }    
}

void MainWindow::saveCustomSetting()
{
    QSettings settings("Vantage", "ComTest");
    settings.setValue("comNum", ui->portNameComboBox->currentIndex());
    settings.setValue("bautRate", ui->baudRateComboBox->currentIndex());
    settings.setValue("dataBit", ui->dataBitsComboBox->currentIndex());
    settings.setValue("parity", ui->parityComboBox->currentIndex());
    settings.setValue("stopBit", ui->stopBitsComboBox->currentIndex());
    settings.setValue("sendMsgCount",ui->sendMsgLineEditComboBox->count());
	settings.setValue("dataDisplay", DataDisplayIndex());
    for(int index = 0; index < ui->sendMsgLineEditComboBox->count(); index++)
    {
       settings.setValue(tr("Msg%1").arg(index),ui->sendMsgLineEditComboBox->itemText(index));
    }
    settings.setValue("delimiter", ui->delimiterLineEdit->text());
}

void MainWindow::loadCustomSetting()
{
    QSettings settings("Vantage", "ComTest");
    ui->portNameComboBox->setCurrentIndex(settings.value("comNum").toInt());
    ui->baudRateComboBox->setCurrentIndex(settings.value("bautRate").toInt());
    ui->dataBitsComboBox->setCurrentIndex(settings.value("dataBit").toInt());
    ui->parityComboBox->setCurrentIndex(settings.value("parity").toInt());
    ui->stopBitsComboBox->setCurrentIndex(settings.value("stopBit").toInt());
	QRadioButton* pRadioButton = GetDataDisplayPointer(DATADISPLAY(settings.value("dataDisplay").toInt()));

	if (pRadioButton)
	{
		pRadioButton->setChecked(true);
	}
	else
	{
		ui->textRadioButton->setChecked(true);
	}

    for(int index = 0; index < settings.value("sendMsgCount").toInt(); index++)
    {
       ui->sendMsgLineEditComboBox->insertItem(index, settings.value(tr("Msg%1").arg(index)).toString());
    }
    ui->delimiterLineEdit->setText(settings.value("delimiter").toString());
}

int MainWindow::DataDisplayIndex()
{
	if (ui->textRadioButton->isChecked())
	{
		return DDY_TEXT;
	}
	else if(ui->hexRadioButton->isChecked())
	{
		return DDY_HEX;
	}
	return DDY_NONE;
}

QRadioButton* MainWindow::GetDataDisplayPointer(DATADISPLAY index)
{
	switch (index)
	{
	case DDY_TEXT:
		return ui->textRadioButton;
	case DDY_HEX:
		return ui->hexRadioButton;
	}
	return NULL;
}

QString MainWindow::EncodebyDataDisplay(QByteArray& data)
{
	QString dataStr;
	QString cellStr;
	if (DDY_HEX == DataDisplayIndex())
	{
		for (int i = 0; i<data.length(); i++)
		{
			int high = ((data[i]>>4) & 0x0F);
			int low = (data[i] & 0x0F);
			cellStr.sprintf("{%x%x}", high, low);
			dataStr.append(cellStr);
		}
	}
	else if(DDY_TEXT == DataDisplayIndex())
	{
		dataStr = data;
	}

	return dataStr;
}

QByteArray MainWindow::DecodebyDataDisplay(QString str)
{
	QByteArray dataStr;	
	if (DDY_HEX == DataDisplayIndex())
	{
		str[0] = ' ';
		str[str.length() - 1] = ' ';
		
		QStringList hexData = str.split("}{");
		QStringListIterator iterator(hexData);
		while(iterator.hasNext())
		{
			bool ok;
			int hex = iterator.next().toInt(&ok, 16);
			if(ok)
				dataStr.append(hex);
		}
	}
	else if(DDY_TEXT == DataDisplayIndex())
	{
		dataStr = str.toAscii();
	}

	return dataStr;
}